home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- (c) Copyright 1984,1985,1986,1987, Front Line Software. All Rights Reserved.
-
- SYS_MEM.C
-
- Release 2.0
-
- Written : 12/23/84 Initial Release
- Updated : 07/16/87 Added more documenation and DOSALLOC.OBJ
-
- By: Front Line Software Co.
- P.O. Box 217
- Lowell, Mass 01853
-
- If you find these functions useful please contribute a small donation
- ( $5.00 ) to help offset the development time. Donations may be sent to
- the above address.
-
- If you can't afford the donation we would still like to get some
- feedback on the number of people that find this useful and/or comments
- on the package. Shareware can be a good deal for both the developers
- and the users, but only if it is supported. We can do alot more
- with shareware packages if it is shown to be worth our time. Let
- us know what you think!
-
- These functions will allow Mark Williams 'C' large model compiler
- (and any other 'C' compiler runnning under MS-DOS Operating System)
- to ALLOC() and FREE() ALL available system memory.
-
- Currently, Mark Williams will only allow a user to ALLOC 64K of
- memory with the Large Model. The user is paying a penalty for using
- the large model (slow pointer arithmetic, slower function calls
- due to pushing the two values on the stack, and less available
- data space due to the double value pointers).
-
- There is no reason why the user should not get the full benefit of
- access to ALL of the memory available in the system. These routines
- allow the user to get the extra memory!
-
- To adapt to another compiler the only routine which will have to be
- changed is the DOSALLOC.ASM routine. The 'entry' and 'exit' code
- which preserves the registers needed by the compiler will have to
- be updated. Check your compiler manual for how to interface to
- assembly language routines. Don't be afraid to try it, it is really
- quite simple.
-
- The SALLOC() and SFREE() functions are used with the exact
- same parameters as ALLOC and FREE as defined in K & R. These are
- the only two points your 'C' program should call. SALLOC will give
- you a pointer to the memory you have asked for, and SFREE will
- place that memory back into the pool.
-
- Compile SYS_MEM.C and link both SYS_MEM.OBJ and DOSALLOC.OBJ with your
- program. Thats it!
-
- We have added DOSALLOC.OBJ to the files as it was pointed out many users
- don't have assemblers.
-
- ******************************************************************************/
-
- #include <stdio.h>
-
- typedef int ALIGN; /* force alignment on IBM PC */
-
- union header { /* sfree block header */
- struct {
- union header *ptr; /* to next sfree block */
- unsigned int size; /* size of this sfree block */
- } s;
- ALIGN x; /* force alignment */
- };
-
- typedef union header HEADER;
- /*****************************************************************************/
-
-
-
- /*****************************************************************************/
- static HEADER base; /* empty list to get started */
- static HEADER *sallocp = NULL; /* last allocated block */
-
- char *salloc(nbytes) /* general-purpose storage allocator */
- unsigned nbytes;
- {
- HEADER *morecore();
- HEADER *p,*q;
- int nunits;
-
-
- if ( nbytes > ( 65535 - sizeof(HEADER) ) )
- return(NULL);
- nunits = 1+(nbytes+sizeof(HEADER)-1)/sizeof(HEADER);
- if ((q = sallocp) == NULL) /* no sfree list yet */
- {
- base.s.ptr = sallocp = q = &base;
- base.s.size = 0;
- }
- for (p=q->s.ptr;; q=p, p=p->s.ptr)
- {
- if ((long)p->s.size >= (long)nunits) /* big enough */
- {
- if ((long)p->s.size == (long)nunits) /* exactly */
- q->s.ptr = p->s.ptr;
- else
- { /* allocate tail end */
- p->s.size -= nunits;
- p += p->s.size;
- p->s.size = nunits;
- }
- sallocp = q;
- return((char *) (p+1));
- }
- if ((long)p == (long)sallocp) /* wrapped around sfree list */
- if (( p = morecore(nunits)) == NULL)
- return(NULL); /* none left */
- }
- }
- /*****************************************************************************/
-
-
-
- /*****************************************************************************/
- #define NSALLOC 2700 /* size of block to get from DOS */
- /* ( NSALLOC X 6 ( 6 is the size of HEADER )
- = SIZE OF BLOCK REQUESTED ) */
-
- static HEADER *morecore(nu) /* asks system(DOS) for memory */
- unsigned nu;
- {
- char *dosalloc();
- char *cp;
- HEADER *up;
- int rnu;
-
- rnu = NSALLOC * ((nu+NSALLOC-1) / NSALLOC);
- cp = dosalloc((unsigned)rnu * sizeof(HEADER));
- if ( (long)cp == NULL ) /* no space available */
- return(NULL);
- up = (HEADER *)cp;
- up->s.size = rnu;
- sfree((char *) (up + 1));
- return(sallocp);
- }
- /*****************************************************************************/
-
-
-
- /*****************************************************************************/
- sfree(ap) /* put block ap in sfree list */
- char *ap;
- {
- HEADER *p, *q;
-
- int h,i,j;
- h = i = j = 0;
-
- p = (HEADER *)ap - 1; /* point to header */
- for (q=sallocp;!((long)p>(long)q && (long)p<(long)q->s.ptr);q=q->s.ptr)
- {
- if ((h=((long)q >= (long)q->s.ptr)) &&
- (((i=((long)p > (long)q)) ||
- (j = ((long)p < (long)q->s.ptr)))))
- break; /* at one end or the other */
- }
-
- if ((long)p+p->s.size == (long)q->s.ptr)/* join to upper nbr */
- {
- p->s.size += q->s.ptr->s.size;
- p->s.ptr = q->s.ptr->s.ptr;
- }
- else
- p->s.ptr = q->s.ptr;
- if ((long)q+q->s.size == (long)p) /* join lower nbr */
- {
- q->s.size += p->s.size;
- q->s.ptr = p->s.ptr;
- }
- else
- q->s.ptr = p;
- sallocp = q;
- }
- /*****************************************************************************/
-